/*
* (C) Copyright 2013 Philip Kirchhoff 
* 
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
* 
*-------------------------------------------------------------------------------
* This file is part of the DataLogger library by Philip Kirchhoff
* https://code.google.com/p/pk-data-logger/
* SVN: http://pk-data-logger.googlecode.com/svn/trunk
*-------------------------------------------------------------------------------
* Module    : DlDataset.cpp   
* Author    : Kirchhoff, Philip
* Date      : 01.04.2013
*-------------------------------------------------------------------------------
* Function definitions for class DlDataset
*   
*-------------------------------------------------------------------------------
* Change History:
* 01.04.2013  Kirchhoff 	Created
--------------------------------------------------------------------------------
*/

#include <iostream>
#include <stdexcept>

#include "DlDataset.h"
#include "DlDataChannel.h"

using namespace std;

/**************************************************************************//**
* @brief Constructs an empty dataset
******************************************************************************/
DlDataset::DlDataset()
    : mSampleRate(1.0)
{
}

/**************************************************************************//**
* @brief CDestructor
******************************************************************************/
DlDataset::~DlDataset()
{
    clear();
}

/**************************************************************************//**
* @brief Clear dataset. This removes all data channel
******************************************************************************/
void DlDataset::clear()
{
    for(unsigned int i = 0; i < mChannels.size(); i++)
        delete mChannels[i];
    mChannels.clear();
}

/**************************************************************************//**
* @brief Creates an empty channel an adds it to the dataset
* @param channelId Channel ID
* @param channelId Channel ID
* @param channelUnit Channel unit (i.e. V, A, ...)
* @return Pointer to channel object
******************************************************************************/
DlDataChannel* DlDataset::newDataChannel(DlDataChannel::ChannelType chanType,
                                         string chanId, string chanUnit,
                                         string chanDescr)
{
    DlDataChannel *ptrChan = 0;

    switch(chanType)
    {
    case DlDataChannel::TYPE_BOOL:
        ptrChan = new DlBoolChannel(mChannels.size(), chanId, chanUnit, chanDescr);
        mChannels.push_back(ptrChan);
        return ptrChan;
    case DlDataChannel::TYPE_LONG:
        ptrChan = new DlLongChannel(mChannels.size(), chanId, chanUnit, chanDescr);
        mChannels.push_back(ptrChan);
        return ptrChan;
    case DlDataChannel::TYPE_ULONG:
        ptrChan = new DlULongChannel(mChannels.size(), chanId, chanUnit, chanDescr);
        mChannels.push_back(ptrChan);
        return ptrChan;
    case DlDataChannel::TYPE_SHORT:
        ptrChan = new DlShortChannel(mChannels.size(), chanId, chanUnit, chanDescr);
        mChannels.push_back(ptrChan);
        return ptrChan;
    case DlDataChannel::TYPE_USHORT:
        ptrChan = new DlUShortChannel(mChannels.size(), chanId, chanUnit, chanDescr);
        mChannels.push_back(ptrChan);
        return ptrChan;
    case DlDataChannel::TYPE_DOUBLE:
        ptrChan = new DlDoubleChannel(mChannels.size(), chanId, chanUnit, chanDescr);
        mChannels.push_back(ptrChan);
        return ptrChan;
    case DlDataChannel::TYPE_FLOAT:
        ptrChan = new DlFloatChannel(mChannels.size(), chanId, chanUnit, chanDescr);
        mChannels.push_back(ptrChan);
        return ptrChan;
    case DlDataChannel::TYPE_STRING:
        ptrChan = new DlStringChannel(mChannels.size(), chanId, chanUnit, chanDescr);
        mChannels.push_back(ptrChan);
        return ptrChan;
    default:
        std::string excString(__PRETTY_FUNCTION__);
        excString += ": Invalid channel type!";
        throw std::runtime_error(excString.c_str());
    }
}

/**************************************************************************//**
* @brief Get a channel from the dataset
* @param chanNum Channel number
* @return Analog channel object
* \details Note than an std::range_error is thrown if chanNum exceeds the
            number of stored channels!
******************************************************************************/
DlDataChannel* DlDataset::channel(unsigned int chanNum)
{
    if(chanNum > mChannels.size()-1)
    {
        std::string excString(__PRETTY_FUNCTION__);
        excString += ": Invalid channel number!";
        throw std::range_error(excString.c_str());
    }
    return mChannels[chanNum];
}

/**************************************************************************//**
* @brief Adds complete a set of samples to the dataset
* @param chanNum Pointer to an array of data samples of varoius types
******************************************************************************/
void DlDataset::addSamples(void **ppSamples)
{
    for(unsigned int i = 0; i < mChannels.size(); i++)
    {
        mChannels[i]->addSample(ppSamples[i]);
    }
}

/**************************************************************************//**
* @brief Get the timestamp offset for a selected sample relative to the start
*			sample
* @param sampleNum Sample number
* @return Timestamp offset in microseconds
******************************************************************************/
double DlDataset::offsetForSample(unsigned int sampleNum)
{
    return (double)sampleNum*(1.0/mSampleRate*1000000.0);
}

/**************************************************************************//**
* @brief Get sample rate
* @return Sample rate
******************************************************************************/
double DlDataset::sampleRate()
{
    return mSampleRate;
}



